#include "linked_stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *trans(char *);
int get_priority(char);
int solve(char *);

int main(int argc, char *argv[]) {

  char *ex = "1+2*3-4";
  ex = trans(ex);
  puts(ex);
  printf("%d\n", solve(ex));
  return 0;
}

int get_priority(char ch) {
  if (ch == '+' || ch == '-') {
    return 1;
  }
  if (ch == '*' || ch == '/') {
    return 2;
  }
  return -1;
}

char *trans(char *ex) {
  char *ret = malloc(sizeof(char) * (strlen(ex) + 1));
  int index = 0;
  Stack *s;
  stack_init(&s, sizeof(char));

  for (int i = 0; i < strlen(ex); i++) {
    if (ex[i] >= '0' && ex[i] <= '9') {
      ret[index++] = ex[i];
      continue;
    } else if (ex[i] == '+' || ex[i] == '-' || ex[i] == '*' || ex[i] == '/') {
      if (stack_empty(s) || *(char *)stack_top(s) == '(') {
        stack_push(s, ex + i);
        continue;
      } else {
        while (!stack_empty(s) &&
               get_priority(ex[i]) <= get_priority(*(char *)stack_top(s))) {
          ret[index++] = *(char *)stack_top(s);
          stack_pop(s);
        }
        stack_push(s, ex + i);
      }
    } else if (ex[i] == '(') {
      stack_push(s, ex + i);
    } else if (ex[i] == ')') {
      while (!stack_empty(s) && *(char *)stack_top(s) != '(') {
        ret[index++] = *(char *)stack_top(s);
        stack_pop(s);
      }
      stack_pop(s);
    }
  }

  while (!stack_empty(s)) {
    ret[index++] = *(char *)stack_top(s);
    stack_pop(s);
  }
  return ret;
}

int solve(char *ex) {
  Stack *s;
  int a, b, c;
  int num;
  stack_init(&s, sizeof(int));
  for (int i = 0; i < strlen(ex); i++) {
    if (ex[i] >= '0' && ex[i] <= '9') {
      num = ex[i] - '0';
      stack_push(s, &num);
    } else {
      b = *(int *)stack_top(s);
      stack_pop(s);
      a = *(int *)stack_top(s);
      stack_pop(s);

      switch (ex[i]) {
      case '+':
        c = a + b;
        break;
      case '-':
        c = a - b;
        break;
      case '*':
        c = a * b;
        break;
      case '/':
        c = a / b;
        break;
      }
      stack_push(s, &c);
    }
  }
  return *(int *)stack_top(s);
}
